﻿using System;
using System.Buffers.Binary;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace JGSY.SerialCommunication.UpperComputer.Component
{
    /// <summary>
    /// Modbus 数据类型枚举
    /// </summary>
    public enum ModbusDataType
    {
        UInt16,     // 无符号16位整数
        Int16,      // 有符号16位整数
        UInt32,     // 无符号32位整数
        Int32,      // 有符号32位整数
        Float,      // 单精度浮点数
        UInt64,     // 无符号64位整数
        Int64,      // 有符号64位整数
        Double      // 双精度浮点数
    }

    /// <summary>
    /// 字节序枚举，定义多字节数据在寄存器中的排列方式
    /// </summary>
    public enum ByteOrder
    {
        BigEndian,      // 高字节在前 (ABCD)
        LittleEndian,   // 低字节在前 (DCBA)
        MidLittleEndian // 字交换 (BADC)
    }

    /// <summary>
    /// Modbus 客户端异常类
    /// </summary>
    public class ModbusException : Exception
    {
        public ModbusException(string message) : base(message) { }
        public ModbusException(string message, Exception innerException) : base(message, innerException) { }
    }

    /// <summary>
    /// Modbus 客户端实现（支持 TCP 和 UDP 协议）
    /// </summary>
    public class ModbusClient : IDisposable
    {
        private readonly string _ipAddress;         // 服务器 IP 地址
        private readonly int _port;                 // 服务器端口
        private readonly ProtocolType _protocolType; // 协议类型（TCP 或 UDP）
        private int _timeout;                       // 超时时间（毫秒）
        private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1); // 连接锁
        private readonly CancellationTokenSource _disposeCts = new CancellationTokenSource(); // 释放令牌
        private Socket _socket;                     // 网络套接字
        private int _transactionId = 0;             // 事务标识符
        private bool _disposed = false;             // 对象是否已释放
        private EndPoint _remoteEndPoint;           // 远程端点缓存

        /// <summary>
        /// 默认字节序，用于多字节数据类型
        /// </summary>
        public ByteOrder DefaultByteOrder { get; set; } = ByteOrder.BigEndian;

        /// <summary>
        /// 获取或设置操作超时时间（毫秒）
        /// </summary>
        public int Timeout
        {
            get => _timeout;
            set
            {
                if (value <= 0)
                    throw new ArgumentException("超时时间必须大于 0", nameof(value));
                _timeout = value;

                // 如果 socket 已创建，更新超时设置
                if (_socket != null)
                {
                    _socket.ReceiveTimeout = value;
                    _socket.SendTimeout = value;
                }
            }
        }

        /// <summary>
        /// 获取客户端是否已连接
        /// </summary>
        public bool IsConnected => _socket != null && IsSocketConnected();

        /// <summary>
        /// 初始化 Modbus 客户端
        /// </summary>
        public ModbusClient(string ipAddress, int port = 502, ProtocolType protocolType = ProtocolType.Tcp, int timeout = 1000)
        {
            if (string.IsNullOrEmpty(ipAddress))
                throw new ArgumentNullException(nameof(ipAddress), "IP地址不能为空");

            if (!IPAddress.TryParse(ipAddress, out _))
                throw new ArgumentException("无效的IP地址", nameof(ipAddress));

            if (port < 1 || port > 65535)
                throw new ArgumentOutOfRangeException(nameof(port), "端口号必须在1-65535之间");

            _ipAddress = ipAddress;
            _port = port;
            _protocolType = protocolType;
            _remoteEndPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
            Timeout = timeout;
        }

        /// <summary>
        /// 连接到 Modbus 服务器
        /// </summary>
        public async Task ConnectAsync()
        {
            ThrowIfDisposed();

            await _connectionLock.WaitAsync(_disposeCts.Token).ConfigureAwait(false);
            try
            {
                if (IsSocketConnected())
                    return;

                SafeCloseSocket();

                _socket = new Socket(AddressFamily.InterNetwork,
                    _protocolType == ProtocolType.Tcp ? SocketType.Stream : SocketType.Dgram,
                    _protocolType);

                _socket.ReceiveTimeout = _timeout;
                _socket.SendTimeout = _timeout;

                if (_protocolType == ProtocolType.Udp)
                {
                    _socket.Bind(new IPEndPoint(IPAddress.Any, 0));
                }
                else
                {
                    try
                    {
                        await _socket.ConnectAsync(_remoteEndPoint, _disposeCts.Token).ConfigureAwait(false);
                    }
                    catch (SocketException ex)
                    {
                        throw new ModbusException($"连接失败: {ex.SocketErrorCode}", ex);
                    }
                }
            }
            finally
            {
                _connectionLock.Release();
            }
        }

        /// <summary>
        /// 断开与服务器的连接
        /// </summary>
        public void Disconnect()
        {
            if (_disposed) return;

            _connectionLock.Wait();
            try
            {
                SafeCloseSocket();
            }
            finally
            {
                _connectionLock.Release();
            }
        }

        /// <summary>
        /// 安全关闭 Socket
        /// </summary>
        private void SafeCloseSocket()
        {
            if (_socket == null) return;

            try
            {
                if (_socket.Connected)
                    _socket.Shutdown(SocketShutdown.Both);
            }
            catch (SocketException) { }
            catch (ObjectDisposedException) { }
            finally
            {
                _socket.Dispose();
                _socket = null;
            }
        }

        /// <summary>
        /// 检查 Socket 连接状态
        /// </summary>
        private bool IsSocketConnected()
        {
            if (_socket == null)
                return false;

            if (_protocolType == ProtocolType.Udp)
            {
                return _socket.IsBound;
            }

            try
            {
                return _socket.Connected
                    && !(_socket.Poll(1000, SelectMode.SelectRead) && _socket.Available == 0);
            }
            catch (SocketException)
            {
                return false;
            }
        }

        #region 基本 Modbus 功能码实现

        /// <summary>
        /// 读取线圈 (功能码 0x01)
        /// </summary>
        public async Task<bool[]> ReadCoils(byte slaveId, ushort startAddress, ushort quantity)
        {
            ValidateQuantity(quantity, 2000);
            var response = await SendRequestAsync(slaveId, 0x01, startAddress, quantity).ConfigureAwait(false);
            return ParseCoilResponse(response, quantity);
        }

        /// <summary>
        /// 读取离散输入 (功能码 0x02)
        /// </summary>
        public async Task<bool[]> ReadDiscreteInputs(byte slaveId, ushort startAddress, ushort quantity)
        {
            ValidateQuantity(quantity, 2000);
            var response = await SendRequestAsync(slaveId, 0x02, startAddress, quantity).ConfigureAwait(false);
            return ParseCoilResponse(response, quantity);
        }

        /// <summary>
        /// 读取保持寄存器 (功能码 0x03)
        /// </summary>
        public async Task<ushort[]> ReadHoldingRegisters(byte slaveId, ushort startAddress, ushort quantity)
        {
            ValidateQuantity(quantity, 125);
            var response = await SendRequestAsync(slaveId, 0x03, startAddress, quantity).ConfigureAwait(false);
            return ParseRegisterResponse(response, quantity);
        }

        /// <summary>
        /// 读取输入寄存器 (功能码 0x04)
        /// </summary>
        public async Task<ushort[]> ReadInputRegisters(byte slaveId, ushort startAddress, ushort quantity)
        {
            ValidateQuantity(quantity, 125);
            var response = await SendRequestAsync(slaveId, 0x04, startAddress, quantity).ConfigureAwait(false);
            return ParseRegisterResponse(response, quantity);
        }

        /// <summary>
        /// 写入单个线圈 (功能码 0x05)
        /// </summary>
        public async Task WriteSingleCoil(byte slaveId, ushort address, bool value)
        {
            ushort coilValue = value ? (ushort)0xFF00 : (ushort)0x0000;
            await SendRequestAsync(slaveId, 0x05, address, coilValue).ConfigureAwait(false);
        }

        /// <summary>
        /// 写入单个寄存器 (功能码 0x06)
        /// </summary>
        public async Task WriteSingleRegister(byte slaveId, ushort address, ushort value)
        {
            await SendRequestAsync(slaveId, 0x06, address, value).ConfigureAwait(false);
        }

        /// <summary>
        /// 写入多个线圈 (功能码 0x0F)
        /// </summary>
        public async Task WriteMultipleCoils(byte slaveId, ushort startAddress, bool[] values)
        {
            if (values == null) throw new ArgumentNullException(nameof(values));
            if (values.Length == 0 || values.Length > 1968)
                throw new ArgumentException("线圈数量必须在 1-1968 之间", nameof(values));

            int byteCount = (values.Length + 7) / 8;
            byte[] data = new byte[byteCount];

            for (int i = 0; i < values.Length; i++)
            {
                if (values[i])
                {
                    int byteIndex = i / 8;
                    int bitIndex = i % 8;
                    data[byteIndex] |= (byte)(1 << bitIndex);
                }
            }

            await SendRequestAsync(slaveId, 0x0F, startAddress, (ushort)values.Length, data).ConfigureAwait(false);
        }

        /// <summary>
        /// 写入多个寄存器 (功能码 0x10)
        /// </summary>
        public async Task WriteMultipleRegisters(byte slaveId, ushort startAddress, ushort[] values)
        {
            if (values == null) throw new ArgumentNullException(nameof(values));
            if (values.Length == 0 || values.Length > 123)
                throw new ArgumentException("寄存器数量必须在 1-123 之间", nameof(values));

            byte[] data = new byte[values.Length * 2];
            for (int i = 0; i < values.Length; i++)
            {
                BinaryPrimitives.WriteUInt16BigEndian(data.AsSpan(i * 2), values[i]);
            }

            await SendRequestAsync(slaveId, 0x10, startAddress, (ushort)values.Length, data).ConfigureAwait(false);
        }

        #endregion

        #region 扩展数据类型支持

        /// <summary>
        /// 读取单个值（支持多种数据类型）
        /// </summary>
        public async Task<T> ReadValueAsync<T>(byte slaveId, ushort startAddress, ByteOrder byteOrder = ByteOrder.BigEndian)
        {
            int registerCount = GetRegisterCount(typeof(T));
            ushort[] registers = await ReadHoldingRegisters(slaveId, startAddress, (ushort)registerCount).ConfigureAwait(false);
            return ConvertRegistersToValue<T>(registers, byteOrder);
        }

        /// <summary>
        /// 写入单个值（支持多种数据类型）
        /// </summary>
        public async Task WriteValueAsync<T>(byte slaveId, ushort startAddress, T value, ByteOrder byteOrder = ByteOrder.BigEndian)
        {
            ushort[] registers = ConvertValueToRegisters(value, byteOrder);
            await WriteMultipleRegisters(slaveId, startAddress, registers).ConfigureAwait(false);
        }

        /// <summary>
        /// 将寄存器值转换为指定类型的值
        /// </summary>
        private T ConvertRegistersToValue<T>(ushort[] registers, ByteOrder byteOrder)
        {
            if (registers == null) throw new ArgumentNullException(nameof(registers));

            Type type = typeof(T);
            byte[] bytes = RegistersToBytes(registers, byteOrder);

            if (type == typeof(float))
                return (T)(object)BitConverter.ToSingle(bytes, 0);
            else if (type == typeof(double))
                return (T)(object)BitConverter.ToDouble(bytes, 0);
            else if (type == typeof(int))
                return (T)(object)BitConverter.ToInt32(bytes, 0);
            else if (type == typeof(uint))
                return (T)(object)BitConverter.ToUInt32(bytes, 0);
            else if (type == typeof(long))
                return (T)(object)BitConverter.ToInt64(bytes, 0);
            else if (type == typeof(ulong))
                return (T)(object)BitConverter.ToUInt64(bytes, 0);
            else if (type == typeof(short))
                return (T)(object)(short)registers[0];
            else if (type == typeof(ushort))
                return (T)(object)registers[0];
            else
                throw new NotSupportedException($"不支持的数据类型: {type.Name}");
        }

        /// <summary>
        /// 将值转换为寄存器数组
        /// </summary>
        private ushort[] ConvertValueToRegisters<T>(T value, ByteOrder byteOrder)
        {
            Type type = typeof(T);
            byte[] bytes;

            if (type == typeof(float))
                bytes = BitConverter.GetBytes((float)(object)value);
            else if (type == typeof(double))
                bytes = BitConverter.GetBytes((double)(object)value);
            else if (type == typeof(int))
                bytes = BitConverter.GetBytes((int)(object)value);
            else if (type == typeof(uint))
                bytes = BitConverter.GetBytes((uint)(object)value);
            else if (type == typeof(long))
                bytes = BitConverter.GetBytes((long)(object)value);
            else if (type == typeof(ulong))
                bytes = BitConverter.GetBytes((ulong)(object)value);
            else if (type == typeof(short))
                bytes = BitConverter.GetBytes((short)(object)value);
            else if (type == typeof(ushort))
                bytes = BitConverter.GetBytes((ushort)(object)value);
            else
                throw new NotSupportedException($"不支持的数据类型: {type.Name}");

            return BytesToRegisters(bytes, byteOrder);
        }

        /// <summary>
        /// 将寄存器转换为字节数组
        /// </summary>
        private byte[] RegistersToBytes(ushort[] registers, ByteOrder byteOrder)
        {
            if (registers == null) throw new ArgumentNullException(nameof(registers));

            byte[] bytes = new byte[registers.Length * 2];

            for (int i = 0; i < registers.Length; i++)
            {
                if (BitConverter.IsLittleEndian)
                {
                    bytes[i * 2] = (byte)(registers[i] >> 8);
                    bytes[i * 2 + 1] = (byte)registers[i];
                }
                else
                {
                    bytes[i * 2] = (byte)registers[i];
                    bytes[i * 2 + 1] = (byte)(registers[i] >> 8);
                }
            }

            if (byteOrder == ByteOrder.LittleEndian)
            {
                Array.Reverse(bytes);
            }
            else if (byteOrder == ByteOrder.MidLittleEndian)
            {
                for (int i = 0; i < bytes.Length; i += 4)
                {
                    if (i + 3 < bytes.Length)
                    {
                        byte temp = bytes[i];
                        bytes[i] = bytes[i + 2];
                        bytes[i + 2] = temp;

                        temp = bytes[i + 1];
                        bytes[i + 1] = bytes[i + 3];
                        bytes[i + 3] = temp;
                    }
                }
            }

            return bytes;
        }

        /// <summary>
        /// 将字节数组转换为寄存器
        /// </summary>
        private ushort[] BytesToRegisters(byte[] bytes, ByteOrder byteOrder)
        {
            if (bytes == null) throw new ArgumentNullException(nameof(bytes));
            if (bytes.Length % 2 != 0)
                throw new ArgumentException("字节数组长度必须为偶数", nameof(bytes));

            byte[] processedBytes = new byte[bytes.Length];
            Array.Copy(bytes, processedBytes, bytes.Length);

            if (byteOrder == ByteOrder.LittleEndian)
            {
                Array.Reverse(processedBytes);
            }
            else if (byteOrder == ByteOrder.MidLittleEndian)
            {
                for (int i = 0; i < processedBytes.Length; i += 4)
                {
                    if (i + 3 < processedBytes.Length)
                    {
                        byte temp = processedBytes[i];
                        processedBytes[i] = processedBytes[i + 2];
                        processedBytes[i + 2] = temp;

                        temp = processedBytes[i + 1];
                        processedBytes[i + 1] = processedBytes[i + 3];
                        processedBytes[i + 3] = temp;
                    }
                }
            }

            ushort[] registers = new ushort[processedBytes.Length / 2];
            for (int i = 0; i < registers.Length; i++)
            {
                registers[i] = BinaryPrimitives.ReadUInt16BigEndian(processedBytes.AsSpan(i * 2, 2));
            }

            return registers;
        }

        /// <summary>
        /// 获取数据类型所需的寄存器数量
        /// </summary>
        private int GetRegisterCount(Type type)
        {
            if (type == typeof(float) || type == typeof(int) || type == typeof(uint))
                return 2;
            else if (type == typeof(double) || type == typeof(long) || type == typeof(ulong))
                return 4;
            else if (type == typeof(short) || type == typeof(ushort))
                return 1;
            else
                throw new NotSupportedException($"不支持的数据类型: {type.Name}");
        }

        #endregion

        #region 私有辅助方法

        /// <summary>
        /// 发送 Modbus 请求并接收响应
        /// </summary>
        private async Task<byte[]> SendRequestAsync(byte slaveId, byte functionCode, ushort address, ushort value, byte[] data = null)
        {
            ThrowIfDisposed();

            await _connectionLock.WaitAsync(_disposeCts.Token).ConfigureAwait(false);
            try
            {
                if (!IsSocketConnected())
                    await ConnectAsync().ConfigureAwait(false);

                ushort transactionId = GetNextTransactionId();
                byte[] request = BuildRequest(transactionId, slaveId, functionCode, address, value, data);

                using var cts = CancellationTokenSource.CreateLinkedTokenSource(
                    _disposeCts.Token,
                    new CancellationTokenSource(_timeout).Token
                );

                try
                {
                    // 发送请求
                    if (_protocolType == ProtocolType.Tcp)
                    {
                        await _socket.SendAsync(request, SocketFlags.None, cts.Token).ConfigureAwait(false);
                    }
                    else
                    {
                        await _socket.SendToAsync(request, SocketFlags.None, _remoteEndPoint, cts.Token).ConfigureAwait(false);
                    }

                    // 接收响应
                    byte[] response;
                    if (_protocolType == ProtocolType.Tcp)
                    {
                        byte[] header = new byte[6];
                        int headerBytesRead = await ReceiveExactAsync(_socket, header, 6, cts.Token).ConfigureAwait(false);
                        if (headerBytesRead != 6)
                            throw new IOException("读取响应头失败");

                        ushort responseTransactionId = BinaryPrimitives.ReadUInt16BigEndian(header.AsSpan(0, 2));
                        if (responseTransactionId != transactionId)
                            throw new InvalidDataException($"事务标识符不匹配，预期: {transactionId}，实际: {responseTransactionId}");

                        ushort responseLength = BinaryPrimitives.ReadUInt16BigEndian(header.AsSpan(4, 2));
                        response = new byte[responseLength];
                        int dataBytesRead = await ReceiveExactAsync(_socket, response, responseLength, cts.Token).ConfigureAwait(false);
                        if (dataBytesRead != responseLength)
                            throw new IOException("读取响应数据失败");
                    }
                    else
                    {
                        response = new byte[1024];
                        var result = await _socket.ReceiveFromAsync(response, SocketFlags.None, _remoteEndPoint, cts.Token).ConfigureAwait(false);
                        Array.Resize(ref response, result.ReceivedBytes);

                        if (response.Length >= 6)
                        {
                            byte[] pdu = new byte[response.Length - 6];
                            Array.Copy(response, 6, pdu, 0, pdu.Length);
                            response = pdu;
                        }
                    }

                    // 检查响应长度
                    if (response.Length < 2)
                        throw new InvalidDataException("响应数据长度不足");

                    // 检查响应功能码
                    byte responseFunctionCode = response[0];
                    if (responseFunctionCode == functionCode + 0x80)
                    {
                        byte errorCode = response[1];
                        throw new ModbusException($"Modbus 异常: 功能码 {functionCode:X2}，错误码 {errorCode:X2}");
                    }

                    if (responseFunctionCode != functionCode)
                        throw new InvalidDataException($"功能码不匹配，预期: {functionCode:X2}，实际: {responseFunctionCode:X2}");

                    return response;
                }
                catch (TaskCanceledException ex)
                {
                    // 操作超时或被取消
                    SafeCloseSocket();
                    throw new ModbusException($"操作超时（{_timeout}ms）", ex);
                }
                catch (SocketException ex)
                {
                    // 网络错误
                    SafeCloseSocket();
                    throw new ModbusException($"通信错误: {ex.SocketErrorCode}", ex);
                }
                catch (Exception ex)
                {
                    // 其他错误
                    SafeCloseSocket();
                    throw new ModbusException($"操作失败: {ex.Message}", ex);
                }
            }
            finally
            {
                _connectionLock.Release();
            }
        }

        /// <summary>
        /// 构建 Modbus 请求报文
        /// </summary>
        private byte[] BuildRequest(ushort transactionId, byte slaveId, byte functionCode, ushort address, ushort value, byte[] data)
        {
            data ??= Array.Empty<byte>();

            int pduLength;
            if (functionCode == 0x0F || functionCode == 0x10) // 写多个线圈或寄存器
            {
                pduLength = 2 + 2 + 1 + data.Length; // 地址(2) + 数量(2) + 字节计数(1) + 数据
            }
            else
            {
                pduLength = 2 + 2; // 地址(2) + 值(2)
            }

            int totalLength = 6 + 1 + pduLength; // MBAP(6) + 从站ID(1) + PDU
            byte[] request = new byte[totalLength];

            // 构建 MBAP 头
            BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(0, 2), transactionId);
            BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(2, 2), 0); // 协议ID
            BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(4, 2), (ushort)(1 + pduLength)); // 后续长度
            request[6] = slaveId; // 从站ID

            // 构建 PDU
            request[7] = functionCode;
            BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(8, 2), address);

            if (functionCode == 0x0F || functionCode == 0x10)
            {
                BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(10, 2), value); // 数量
                request[12] = (byte)data.Length; // 字节计数

                // 复制数据
                if (data.Length > 0)
                {
                    data.CopyTo(request.AsSpan(13));
                }
            }
            else
            {
                BinaryPrimitives.WriteUInt16BigEndian(request.AsSpan(10, 2), value); // 值
            }

            return request;
        }

        /// <summary>
        /// 解析线圈响应
        /// </summary>
        private bool[] ParseCoilResponse(byte[] response, ushort expectedQuantity)
        {
            if (response == null || response.Length < 3)
                throw new ArgumentException("响应数据无效", nameof(response));

            byte byteCount = response[1];
            int expectedByteCount = (expectedQuantity + 7) / 8;

            if (byteCount != expectedByteCount)
                throw new InvalidDataException($"字节计数不匹配，预期: {expectedByteCount}，实际: {byteCount}");

            bool[] values = new bool[expectedQuantity];
            // 将字节数组转换为布尔数组
            for (int i = 0; i < byteCount; i++)
            {
                byte b = response[i + 2];
                for (int j = 0; j < 8; j++)
                {
                    int index = i * 8 + j;
                    if (index >= expectedQuantity)
                        break;
                    values[index] = (b & (1 << j)) != 0;
                }
            }

            return values;
        }

        /// <summary>
        /// 解析寄存器响应
        /// </summary>
        private ushort[] ParseRegisterResponse(byte[] response, ushort expectedQuantity)
        {
            if (response == null || response.Length < 3)
                throw new ArgumentException("响应数据无效", nameof(response));

            byte byteCount = response[1];
            int expectedByteCount = expectedQuantity * 2;

            if (byteCount != expectedByteCount)
                throw new InvalidDataException($"字节计数不匹配，预期: {expectedByteCount}，实际: {byteCount}");

            ushort[] values = new ushort[expectedQuantity];

            for (int i = 0; i < expectedQuantity; i++)
            {
                values[i] = BinaryPrimitives.ReadUInt16BigEndian(response.AsSpan(2 + i * 2, 2));
            }

            return values;
        }

        /// <summary>
        /// 接收指定数量的字节
        /// </summary>
        private async Task<int> ReceiveExactAsync(Socket socket, byte[] buffer, int count, CancellationToken cancellationToken)
        {
            int totalBytesRead = 0;
            while (totalBytesRead < count && !cancellationToken.IsCancellationRequested)
            {
                int bytesRead = await socket.ReceiveAsync(
                    buffer.AsMemory(totalBytesRead, count - totalBytesRead),
                    SocketFlags.None,
                    cancellationToken).ConfigureAwait(false);

                if (bytesRead == 0)
                    break; // 连接关闭

                totalBytesRead += bytesRead;
            }

            return totalBytesRead;
        }

        /// <summary>
        /// 获取下一个事务标识符
        /// </summary>
        private ushort GetNextTransactionId()
        {
            return (ushort)Interlocked.Increment(ref _transactionId);
        }

        /// <summary>
        /// 验证数量是否在允许范围内
        /// </summary>
        private void ValidateQuantity(ushort quantity, int max)
        {
            if (quantity < 1 || quantity > max)
                throw new ArgumentException($"数量必须在 1-{max} 之间", nameof(quantity));
        }

        /// <summary>
        /// 检查对象是否已释放
        /// </summary>
        private void ThrowIfDisposed()
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(ModbusClient));
        }

        #endregion

        #region 资源释放

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源的实现
        /// </summary>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _disposeCts.Cancel();
                    _disposeCts.Dispose();
                    _connectionLock.Dispose();
                    SafeCloseSocket();
                }
                _disposed = true;
            }
        }

        #endregion

        /// <summary>
        /// 重新连接到服务器
        /// </summary>
        public async Task ReconnectAsync()
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(ModbusClient));

            await _connectionLock.WaitAsync(_disposeCts.Token).ConfigureAwait(false);
            try
            {
                SafeCloseSocket();
                await ConnectAsync().ConfigureAwait(false);
            }
            finally
            {
                _connectionLock.Release();
            }
        }
    }
}